home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / jpeg / jcmain.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  21KB  |  699 lines

  1. /*
  2.  * jcmain.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  */
  22.  
  23. #include "jinclude.h"
  24. #ifdef INCLUDES_ARE_ANSI
  25. #include <stdlib.h>        /* to declare exit() */
  26. #endif
  27. #include <ctype.h>        /* to declare isupper(), tolower() */
  28. #ifdef NEED_SIGNAL_CATCHER
  29. #include <signal.h>        /* to declare signal() */
  30. #endif
  31. #ifdef USE_SETMODE
  32. #include <fcntl.h>        /* to declare setmode() */
  33. #endif
  34.  
  35. #ifdef THINK_C
  36. #include <console.h>        /* command-line reader for Macintosh */
  37. #endif
  38.  
  39. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  40. #define READ_BINARY    "r"
  41. #define WRITE_BINARY    "w"
  42. #else
  43. #define READ_BINARY    "rb"
  44. #define WRITE_BINARY    "wb"
  45. #endif
  46.  
  47. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  48. #define EXIT_FAILURE  1
  49. #endif
  50. #ifndef EXIT_SUCCESS
  51. #ifdef VMS
  52. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  53. #else
  54. #define EXIT_SUCCESS  0
  55. #endif
  56. #endif
  57.  
  58.  
  59. #include "jversion.h"        /* for version message */
  60.  
  61.  
  62. /*
  63.  * This routine determines what format the input file is,
  64.  * and selects the appropriate input-reading module.
  65.  *
  66.  * To determine which family of input formats the file belongs to,
  67.  * we may look only at the first byte of the file, since C does not
  68.  * guarantee that more than one character can be pushed back with ungetc.
  69.  * Looking at additional bytes would require one of these approaches:
  70.  *     1) assume we can fseek() the input file (fails for piped input);
  71.  *     2) assume we can push back more than one character (works in
  72.  *        some C implementations, but unportable);
  73.  *     3) provide our own buffering as is done in djpeg (breaks input readers
  74.  *        that want to use stdio directly, such as the RLE library);
  75.  * or  4) don't put back the data, and modify the input_init methods to assume
  76.  *        they start reading after the start of file (also breaks RLE library).
  77.  * #1 is attractive for MS-DOS but is untenable on Unix.
  78.  *
  79.  * The most portable solution for file types that can't be identified by their
  80.  * first byte is to make the user tell us what they are.  This is also the
  81.  * only approach for "raw" file types that contain only arbitrary values.
  82.  * We presently apply this method for Targa files.  Most of the time Targa
  83.  * files start with 0x00, so we recognize that case.  Potentially, however,
  84.  * a Targa file could start with any byte value (byte 0 is the length of the
  85.  * seldom-used ID field), so we provide a switch to force Targa input mode.
  86.  */
  87.  
  88. static boolean is_targa;    /* records user -targa switch */
  89.  
  90.  
  91. LOCAL void
  92. select_file_type (compress_info_ptr cinfo)
  93. {
  94.   int c;
  95.  
  96.   if (is_targa) {
  97. #ifdef TARGA_SUPPORTED
  98.     jselrtarga(cinfo);
  99. #else
  100.     ERREXIT(cinfo->emethods, "Targa support was not compiled");
  101. #endif
  102.     return;
  103.   }
  104.  
  105.   if ((c = getc(cinfo->input_file)) == EOF)
  106.     ERREXIT(cinfo->emethods, "Empty input file");
  107.  
  108.   switch (c) {
  109. #ifdef GIF_SUPPORTED
  110.   case 'G':
  111.     jselrgif(cinfo);
  112.     break;
  113. #endif
  114. #ifdef PPM_SUPPORTED
  115.   case 'P':
  116.     jselrppm(cinfo);
  117.     break;
  118. #endif
  119. #ifdef RLE_SUPPORTED
  120.   case 'R':
  121.     jselrrle(cinfo);
  122.     break;
  123. #endif
  124. #ifdef SGI_SUPPORTED
  125.   case 0x01:
  126.   case 0xda:
  127.     jselrsgi(cinfo);
  128.     break;
  129. #endif
  130. #ifdef TARGA_SUPPORTED
  131.   case 0x00:
  132.     jselrtarga(cinfo);
  133.     break;
  134. #endif
  135.   default:
  136. #ifdef TARGA_SUPPORTED
  137.     ERREXIT(cinfo->emethods, "Unrecognized input file format --- perhaps you need -targa");
  138. #else
  139.     ERREXIT(cinfo->emethods, "Unrecognized input file format");
  140. #endif
  141.     break;
  142.   }
  143.  
  144.   if (ungetc(c, cinfo->input_file) == EOF)
  145.     ERREXIT(cinfo->emethods, "ungetc failed");
  146. }
  147.  
  148.  
  149. /*
  150.  * This routine gets control after the input file header has been read.
  151.  * It must determine what output JPEG file format is to be written,
  152.  * and make any other compression parameter changes that are desirable.
  153.  */
  154.  
  155. METHODDEF void
  156. c_ui_method_selection (compress_info_ptr cinfo)
  157. {
  158.   /* If the input is gray scale, generate a monochrome JPEG file. */
  159.   if (cinfo->in_color_space == CS_GRAYSCALE)
  160.     j_monochrome_default(cinfo);
  161.   /* For now, always select JFIF output format. */
  162. #ifdef JFIF_SUPPORTED
  163.   jselwjfif(cinfo);
  164. #else
  165.   You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  166. #endif
  167. }
  168.  
  169.  
  170. /*
  171.  * Signal catcher to ensure that temporary files are removed before aborting.
  172.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  173.  * see -Dsignal_catcher=_abort in CFLAGS.  Talk about bogus...
  174.  */
  175.  
  176. #ifdef NEED_SIGNAL_CATCHER
  177.  
  178. static external_methods_ptr emethods; /* for access to free_all */
  179.  
  180. GLOBAL void
  181. signal_catcher (int signum)
  182. {
  183.   if (emethods != NULL) {
  184.     emethods->trace_level = 0;    /* turn off trace output */
  185.     (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  186.   }
  187.   exit(EXIT_FAILURE);
  188. }
  189.  
  190. #endif
  191.  
  192.  
  193. /*
  194.  * Optional routine to display a percent-done figure on stderr.
  195.  * See jcdeflts.c for explanation of the information used.
  196.  */
  197.  
  198. #ifdef PROGRESS_REPORT
  199.  
  200. METHODDEF void
  201. progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit)
  202. {
  203.   if (cinfo->total_passes > 1) {
  204.     fprintf(stderr, "\rPass %d/%d: %3d%% ",
  205.         cinfo->completed_passes+1, cinfo->total_passes,
  206.         (int) (loopcounter*100L/looplimit));
  207.   } else {
  208.     fprintf(stderr, "\r %3d%% ",
  209.         (int) (loopcounter*100L/looplimit));
  210.   }
  211.   fflush(stderr);
  212. }
  213.  
  214. #endif
  215.  
  216.  
  217. /*
  218.  * Argument-parsing code.
  219.  * The switch parser is designed to be useful with DOS-style command line
  220.  * syntax, ie, intermixed switches and file names, where only the switches
  221.  * to the left of a given file name affect processing of that file.
  222.  * The main program in this file doesn't actually use this capability...
  223.  */
  224.  
  225.  
  226. static char * progname;        /* program name for error messages */
  227.  
  228.  
  229. LOCAL void
  230. usage (void)
  231. /* complain about bad command line */
  232. {
  233.   fprintf(stderr, "usage: %s [switches] ", progname);
  234. #ifdef TWO_FILE_COMMANDLINE
  235.   fprintf(stderr, "inputfile outputfile\n");
  236. #else
  237.   fprintf(stderr, "[inputfile]\n");
  238. #endif
  239.  
  240.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  241.   fprintf(stderr, "  -quality N     Compression quality (0..100; 5-95 is useful range)\n");
  242.   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
  243. #ifdef ENTROPY_OPT_SUPPORTED
  244.   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
  245. #endif
  246. #ifdef TARGA_SUPPORTED
  247.   fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n");
  248. #endif
  249.   fprintf(stderr, "Switches for advanced users:\n");
  250.   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
  251. #ifdef INPUT_SMOOTHING_SUPPORTED
  252.   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
  253. #endif
  254.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  255.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  256.   fprintf(stderr, "Switches for wizards:\n");
  257. #ifdef C_ARITH_CODING_SUPPORTED
  258.   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
  259. #endif
  260. #ifdef C_MULTISCAN_FILES_SUPPORTED
  261.   fprintf(stderr, "  -nointerleave  Create noninterleaved JPEG file\n");
  262. #endif
  263.   fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
  264.   fprintf(stderr, "  -sample HxV[,...]  Set JPEG sampling factors\n");
  265.   exit(EXIT_FAILURE);
  266. }
  267.  
  268.  
  269. LOCAL boolean
  270. keymatch (char * arg, const char * keyword, int minchars)
  271. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  272. /* keyword is the constant keyword (must be lower case already), */
  273. /* minchars is length of minimum legal abbreviation. */
  274. {
  275.   register int ca, ck;
  276.   register int nmatched = 0;
  277.  
  278.   while ((ca = *arg++) != '\0') {
  279.     if ((ck = *keyword++) == '\0')
  280.       return FALSE;        /* arg longer than keyword, no good */
  281.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  282.       ca = tolower(ca);
  283.     if (ca != ck)
  284.       return FALSE;        /* no good */
  285.     nmatched++;            /* count matched characters */
  286.   }
  287.   /* reached end of argument; fail if it's too short for unique abbrev */
  288.   if (nmatched < minchars)
  289.     return FALSE;
  290.   return TRUE;            /* A-OK */
  291. }
  292.  
  293.  
  294. LOCAL int
  295. qt_getc (FILE * file)
  296. /* Read next char, skipping over any comments (# to end of line) */
  297. /* A comment/newline sequence is returned as a newline */
  298. {
  299.   register int ch;
  300.   
  301.   ch = getc(file);
  302.   if (ch == '#') {
  303.     do {
  304.       ch = getc(file);
  305.     } while (ch != '\n' && ch != EOF);
  306.   }
  307.   return ch;
  308. }
  309.  
  310.  
  311. LOCAL long
  312. read_qt_integer (FILE * file)
  313. /* Read an unsigned decimal integer from a quantization-table file */
  314. /* Swallows one trailing character after the integer */
  315. {
  316.   register int ch;
  317.   register long val;
  318.   
  319.   /* Skip any leading whitespace, detect EOF */
  320.   do {
  321.     ch = qt_getc(file);
  322.     if (ch == EOF)
  323.       return EOF;
  324.   } while (isspace(ch));
  325.   
  326.   if (! isdigit(ch)) {
  327.     fprintf(stderr, "%s: bogus data in quantization file\n", progname);
  328.     exit(EXIT_FAILURE);
  329.   }
  330.  
  331.   val = ch - '0';
  332.   while (ch = qt_getc(file), isdigit(ch)) {
  333.     val *= 10;
  334.     val += ch - '0';
  335.   }
  336.   return val;
  337. }
  338.  
  339.  
  340. LOCAL void
  341. read_quant_tables (compress_info_ptr cinfo, char * filename, int scale_factor)
  342. /* Read a set of quantization tables from the specified file.
  343.  * The file is plain ASCII text: decimal numbers with whitespace between.
  344.  * Comments preceded by '#' may be included in the file.
  345.  * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
  346.  * The tables are implicitly numbered 0,1,etc.
  347.  */
  348. {
  349.   /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
  350.   /* read in natural order (left to right, top to bottom). */
  351.   static const short ZIG[DCTSIZE2] = {
  352.      0,  1,  5,  6, 14, 15, 27, 28,
  353.      2,  4,  7, 13, 16, 26, 29, 42,
  354.      3,  8, 12, 17, 25, 30, 41, 43,
  355.      9, 11, 18, 24, 31, 40, 44, 53,
  356.     10, 19, 23, 32, 39, 45, 52, 54,
  357.     20, 22, 33, 38, 46, 51, 55, 60,
  358.     21, 34, 37, 47, 50, 56, 59, 61,
  359.     35, 36, 48, 49, 57, 58, 62, 63
  360.     };
  361.   FILE * fp;
  362.   int tblno, i;
  363.   long val;
  364.   QUANT_TBL table;
  365.  
  366.   if ((fp = fopen(filename, "r")) == NULL) {
  367.     fprintf(stderr, "%s: can't open %s\n", progname, filename);
  368.     exit(EXIT_FAILURE);
  369.   }
  370.   tblno = 0;
  371.  
  372.   while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
  373.     if (tblno >= NUM_QUANT_TBLS) {
  374.       fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
  375.       exit(EXIT_FAILURE);
  376.     }
  377.     table[0] = (QUANT_VAL) val;
  378.     for (i = 1; i < DCTSIZE2; i++) {
  379.       if ((val = read_qt_integer(fp)) == EOF) {
  380.     fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
  381.     exit(EXIT_FAILURE);
  382.       }
  383.       table[ZIG[i]] = (QUANT_VAL) val;
  384.     }
  385.     j_add_quant_table(cinfo, tblno, table, scale_factor, FALSE);
  386.     tblno++;
  387.   }
  388.  
  389.   fclose(fp);
  390. }
  391.  
  392.  
  393. LOCAL void
  394. set_sample_factors (compress_info_ptr cinfo, char *arg)
  395. /* Process a sample-factors parameter string, of the form */
  396. /*     HxV[,HxV,...]    */
  397. {
  398. #define MAX_COMPONENTS 4    /* # of comp_info slots made by jcdeflts.c */
  399.   int ci, val1, val2;
  400.   char ch1, ch2;
  401.  
  402.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  403.     if (*arg) {
  404.       ch2 = ',';        /* if not set by sscanf, will be ',' */
  405.       if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
  406.     usage();
  407.       if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
  408.     usage();        /* syntax check */
  409.       if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
  410.     fprintf(stderr, "JPEG sampling factors must be 1..4\n");
  411.     exit(EXIT_FAILURE);
  412.       }
  413.       cinfo->comp_info[ci].h_samp_factor = val1;
  414.       cinfo->comp_info[ci].v_samp_factor = val2;
  415.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  416.     ;
  417.     } else {
  418.       /* reached end of parameter, set remaining components to 1x1 sampling */
  419.       cinfo->comp_info[ci].h_samp_factor = 1;
  420.       cinfo->comp_info[ci].v_samp_factor = 1;
  421.     }
  422.   }
  423. }
  424.  
  425.  
  426. LOCAL int
  427. parse_switches (compress_info_ptr cinfo, int last_file_arg_seen,
  428.         int argc, char **argv)
  429. /* Initialize cinfo with default switch settings, then parse option switches.
  430.  * Returns argv[] index of first file-name argument (== argc if none).
  431.  * Any file names with indexes <= last_file_arg_seen are ignored;
  432.  * they have presumably been processed in a previous iteration.
  433.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  434.  */
  435. {
  436.   int argn;
  437.   char * arg;
  438.   char * qtablefile = NULL;    /* saves -qtables filename if any */
  439.   int q_scale_factor = 100;    /* default to no scaling for -qtables */
  440.  
  441.   /* (Re-)initialize the system-dependent error and memory managers. */
  442.   jselerror(cinfo->emethods);    /* error/trace message routines */
  443.   jselmemmgr(cinfo->emethods);    /* memory allocation routines */
  444.   cinfo->methods->c_ui_method_selection = c_ui_method_selection;
  445.  
  446.   /* Now OK to enable signal catcher. */
  447. #ifdef NEED_SIGNAL_CATCHER
  448.   emethods = cinfo->emethods;
  449. #endif
  450.  
  451.   /* Set up default JPEG parameters. */
  452.   /* Note that default -quality level here need not, and does not,
  453.    * match the default scaling for an explicit -qtables argument.
  454.    */
  455.   j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */
  456.   is_targa = FALSE;
  457.  
  458.   /* Scan command line options, adjust parameters */
  459.  
  460.   for (argn = 1; argn < argc; argn++) {
  461.     arg = argv[argn];
  462.     if (*arg != '-') {
  463.       /* Not a switch, must be a file name argument */
  464.       if (argn <= last_file_arg_seen)
  465.     continue;        /* ignore it if previously processed */
  466.       break;            /* else done parsing switches */
  467.     }
  468.     arg++;            /* advance past switch marker character */
  469.  
  470.     if (keymatch(arg, "arithmetic", 1)) {
  471.       /* Use arithmetic coding. */
  472. #ifdef C_ARITH_CODING_SUPPORTED
  473.       cinfo->arith_code = TRUE;
  474. #else
  475.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  476.           progname);
  477.       exit(EXIT_FAILURE);
  478. #endif
  479.  
  480.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  481.       /* Enable debug printouts. */
  482.       /* On first -d, print version identification */
  483.       if (last_file_arg_seen == 0 && cinfo->emethods->trace_level == 0)
  484.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  485.         JVERSION, JCOPYRIGHT);
  486.       cinfo->emethods->trace_level++;
  487.  
  488.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  489.       /* Force a monochrome JPEG file to be generated. */
  490.       j_monochrome_default(cinfo);
  491.  
  492.     } else if (keymatch(arg, "maxmemory", 1)) {
  493.       /* Maximum memory in Kb (or Mb with 'm'). */
  494.       long lval;
  495.       char ch = 'x';
  496.  
  497.       if (++argn >= argc)    /* advance to next argument */
  498.     usage();
  499.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  500.     usage();
  501.       if (ch == 'm' || ch == 'M')
  502.     lval *= 1000L;
  503.       cinfo->emethods->max_memory_to_use = lval * 1000L;
  504.  
  505.     } else if (keymatch(arg, "nointerleave", 3)) {
  506.       /* Create noninterleaved file. */
  507. #ifdef C_MULTISCAN_FILES_SUPPORTED
  508.       cinfo->interleave = FALSE;
  509. #else
  510.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  511.           progname);
  512.       exit(EXIT_FAILURE);
  513. #endif
  514.  
  515.     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  516.       /* Enable entropy parm optimization. */
  517. #ifdef ENTROPY_OPT_SUPPORTED
  518.       cinfo->optimize_coding = TRUE;
  519. #else
  520.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  521.           progname);
  522.       exit(EXIT_FAILURE);
  523. #endif
  524.  
  525.     } else if (keymatch(arg, "quality", 1)) {
  526.       /* Quality factor (quantization table scaling factor). */
  527.       int val;
  528.  
  529.       if (++argn >= argc)    /* advance to next argument */
  530.     usage();
  531.       if (sscanf(argv[argn], "%d", &val) != 1)
  532.     usage();
  533.       /* Set quantization tables (will be overridden if -qtables also given).
  534.        * Note: we make force_baseline FALSE.
  535.        * This means non-baseline JPEG files can be created with low Q values.
  536.        * To ensure only baseline files are generated, pass TRUE instead.
  537.        */
  538.       j_set_quality(cinfo, val, FALSE);
  539.       /* Change scale factor in case -qtables is present. */
  540.       q_scale_factor = j_quality_scaling(val);
  541.  
  542.     } else if (keymatch(arg, "qtables", 2)) {
  543.       /* Quantization tables fetched from file. */
  544.       if (++argn >= argc)    /* advance to next argument */
  545.     usage();
  546.       qtablefile = argv[argn];
  547.       /* we postpone actually reading the file in case -quality comes later */
  548.  
  549.     } else if (keymatch(arg, "restart", 1)) {
  550.       /* Restart interval in MCU rows (or in MCUs with 'b'). */
  551.       long lval;
  552.       char ch = 'x';
  553.  
  554.       if (++argn >= argc)    /* advance to next argument */
  555.     usage();
  556.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  557.     usage();
  558.       if (lval < 0 || lval > 65535L)
  559.     usage();
  560.       if (ch == 'b' || ch == 'B')
  561.     cinfo->restart_interval = (UINT16) lval;
  562.       else
  563.     cinfo->restart_in_rows = (int) lval;
  564.  
  565.     } else if (keymatch(arg, "sample", 2)) {
  566.       /* Set sampling factors. */
  567.       if (++argn >= argc)    /* advance to next argument */
  568.     usage();
  569.       set_sample_factors(cinfo, argv[argn]);
  570.  
  571.     } else if (keymatch(arg, "smooth", 2)) {
  572.       /* Set input smoothing factor. */
  573.       int val;
  574.  
  575.       if (++argn >= argc)    /* advance to next argument */
  576.     usage();
  577.       if (sscanf(argv[argn], "%d", &val) != 1)
  578.     usage();
  579.       if (val < 0 || val > 100)
  580.     usage();
  581.       cinfo->smoothing_factor = val;
  582.  
  583.     } else if (keymatch(arg, "targa", 1)) {
  584.       /* Input file is Targa format. */
  585.       is_targa = TRUE;
  586.  
  587.     } else {
  588.       usage();            /* bogus switch */
  589.     }
  590.   }
  591.  
  592.   /* Post-switch-scanning cleanup */
  593.  
  594.   if (qtablefile != NULL)    /* process -qtables if it was present */
  595.     read_quant_tables(cinfo, qtablefile, q_scale_factor);
  596.  
  597.   return argn;            /* return index of next arg (file name) */
  598. }
  599.  
  600.  
  601. /*
  602.  * The main program.
  603.  */
  604.  
  605. GLOBAL int
  606. main (int argc, char **argv)
  607. {
  608.   struct Compress_info_struct cinfo;
  609.   struct Compress_methods_struct c_methods;
  610.   struct External_methods_struct e_methods;
  611.   int file_index;
  612.  
  613.   /* On Mac, fetch a command line. */
  614. #ifdef THINK_C
  615.   argc = ccommand(&argv);
  616. #endif
  617.  
  618.   progname = argv[0];
  619.  
  620.   /* Set up links to method structures. */
  621.   cinfo.methods = &c_methods;
  622.   cinfo.emethods = &e_methods;
  623.  
  624.   /* Install, but don't yet enable signal catcher. */
  625. #ifdef NEED_SIGNAL_CATCHER
  626.   emethods = NULL;
  627.   signal(SIGINT, signal_catcher);
  628. #ifdef SIGTERM            /* not all systems have SIGTERM */
  629.   signal(SIGTERM, signal_catcher);
  630. #endif
  631. #endif
  632.  
  633.   /* Scan command line: set up compression parameters, input & output files. */
  634.  
  635.   file_index = parse_switches(&cinfo, 0, argc, argv);
  636.  
  637. #ifdef TWO_FILE_COMMANDLINE
  638.  
  639.   if (file_index != argc-2) {
  640.     fprintf(stderr, "%s: must name one input and one output file\n", progname);
  641.     usage();
  642.   }
  643.   if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  644.     fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  645.     exit(EXIT_FAILURE);
  646.   }
  647.   if ((cinfo.output_file = fopen(argv[file_index+1], WRITE_BINARY)) == NULL) {
  648.     fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index+1]);
  649.     exit(EXIT_FAILURE);
  650.   }
  651.  
  652. #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
  653.  
  654.   cinfo.input_file = stdin;    /* default input file */
  655.   cinfo.output_file = stdout;    /* always the output file */
  656.  
  657. #ifdef USE_SETMODE        /* need to hack file mode? */
  658.   setmode(fileno(stdin), O_BINARY);
  659.   setmode(fileno(stdout), O_BINARY);
  660. #endif
  661.  
  662.   if (file_index < argc-1) {
  663.     fprintf(stderr, "%s: only one input file\n", progname);
  664.     usage();
  665.   }
  666.   if (file_index < argc) {
  667.     if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  668.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  669.       exit(EXIT_FAILURE);
  670.     }
  671.   }
  672.  
  673. #endif /* TWO_FILE_COMMANDLINE */
  674.  
  675.   /* Figure out the input file format, and set up to read it. */
  676.   select_file_type(&cinfo);
  677.  
  678. #ifdef PROGRESS_REPORT
  679.   /* Start up progress display, unless trace output is on */
  680.   if (e_methods.trace_level == 0)
  681.     c_methods.progress_monitor = progress_monitor;
  682. #endif
  683.  
  684.   /* Do it to it! */
  685.   jpeg_compress(&cinfo);
  686.  
  687. #ifdef PROGRESS_REPORT
  688.   /* Clear away progress display */
  689.   if (e_methods.trace_level == 0) {
  690.     fprintf(stderr, "\r                \r");
  691.     fflush(stderr);
  692.   }
  693. #endif
  694.  
  695.   /* All done. */
  696.   exit(EXIT_SUCCESS);
  697.   return 0;            /* suppress no-return-value warnings */
  698. }
  699.